<template>
  <el-dialog draggable title="授权菜单" v-model="isShowDialog" width="620px" :close-on-click-modal="false" destroy-on-close>
    <div class="auth-menu-container" v-loading="loading">
      <div class="menu-header">
        <el-input v-model="filterText" placeholder="搜索菜单" clearable prefix-icon="Search" class="search-input" />
        <el-checkbox v-model="checkAll" size="large" @change="handleCheckAllChange" class="check-all"> 全选/取消全选 </el-checkbox>
      </div>

      <div class="menu-tree">
        <el-tree
          ref="treeRef"
          v-if="isShowDialog"
          :check-strictly="checkStrictly"
          default-expand-all
          node-key="menuId"
          :filter-node-method="filterNode"
          show-checkbox
          :data="menuTree"
          @check-change="handleCheckChange"
          class="permission-tree"
        >
          <template #default="{ node, data }">
            <div class="custom-tree-node">
              <el-icon class="menu-icon">
                <component :is="data.meta.icon" />
              </el-icon>
              <span class="menu-title">{{ data.meta.title }}</span>
            </div>
          </template>
        </el-tree>
      </div>
    </div>

    <template #footer>
      <el-button @click="closeDialog">取 消</el-button>
      <el-button type="primary" :loading="loading" @click="saveAuth"> 确 定 </el-button>
    </template>
  </el-dialog>
</template>

<script setup>
  import { useMenuApi } from '@/api/menu-api.js';
  import { useRoleApi } from '@/api/role-api.js';
  import { RStatus } from '@/common/comstants.js';
  import { updateRoute } from '@/utils/router-update-util.js';

  /** 加载控制 */
  let loading = ref(false);
  /** 弹窗显示控制 */
  let isShowDialog = ref(false);
  /** 菜单树图 */
  let menuTree = ref([]);
  /** 查询菜单字段 */
  let filterText = ref('');
  /** 当前被选中的节点 */
  let selectedNodeKeys = ref([]);
  /** 角色id */
  let roleId = ref(null);
  /** 是否全选 */
  let checkAll = ref(false);
  /** 菜单列表 */
  let menuList = ref([]);
  /** el-tree组件是否严格的遵循父子不互相关联的做法 */
  let checkStrictly = ref(true);

  /** 定义子组件向父组件传值/事件 */
  const _emit = defineEmits(['refresh']);
  /**树图ref */
  const treeRef = ref(null);

  watch(filterText, (val) => {
    treeRef.value.filter(val);
  });

  /** 打开弹框 */
  const openDialog = (row) => {
    checkStrictly.value = true;
    isShowDialog.value = true;
    roleId.value = row.roleId;
    getMenuList();
  };

  /** 获取菜单列表 */
  const getMenuList = async () => {
    loading.value = true;
    try {
      const res = await useMenuApi().getList();
      if (res.status === RStatus.SUCCESS) {
        menuList.value = res.data;
        menuTree.value = updateRoute(res.data);
        getAuthMenuList();
      }
    } finally {
      loading.value = false;
    }
  };

  /** 获取已授权菜单列表 */
  const getAuthMenuList = async () => {
    loading.value = true;
    try {
      const res = await useRoleApi().getRoleMenuList(roleId.value);
      if (res.status === RStatus.SUCCESS) {
        treeRef.value.setCheckedKeys(res.data.map((item) => item.menuId));
        checkStrictly.value = false;
      }
    } finally {
      loading.value = false;
    }
  };

  /** 选中菜单发生改变时调用 */
  const handleCheckChange = (node, checked) => {
    selectedNodeKeys.value = [...treeRef.value.getCheckedKeys(), ...treeRef.value.getHalfCheckedKeys()];
    updateCheckAll();
  };

  /** 更新是否全选 */
  const updateCheckAll = () => {
    if (menuList.value.length === selectedNodeKeys.value.length) {
      checkAll.value = true;
    } else {
      checkAll.value = false;
    }
  };

  /** 选中所有 */
  const handleCheckAllChange = (checked) => {
    if (checked) {
      treeRef.value.setCheckedKeys(menuTree.value.map((item) => item.menuId));
    } else {
      treeRef.value.setCheckedKeys([]);
    }
  };

  /** 帅选菜单 */
  const filterNode = (value, data) => {
    if (!value) return true;
    return data.meta.title.includes(value);
  };

  /** 保存 */
  const saveAuth = async () => {
    loading.value = true;
    try {
      const res = await useRoleApi().updateRoleMenu({
        roleId: roleId.value,
        menuIds: selectedNodeKeys.value,
      });
      if (res.status === RStatus.SUCCESS) {
        ElMessage.success(res.message);
        closeDialog();
      }
    } finally {
      loading.value = false;
    }
  };

  /** 关闭弹框 */
  const closeDialog = () => {
    isShowDialog.value = false;
  };

  defineExpose({
    openDialog,
  });
</script>

<style lang="scss" scoped>
  .auth-menu-container {
    padding: 15px;

    .menu-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 20px;

      .search-input {
        flex-grow: 1;
        margin-right: 15px;

        :deep(.el-input__wrapper) {
          background-color: #ffffff;
          border: 1px solid #e0e6ed;
          border-radius: 8px;
          transition: all 0.3s ease;

          &:hover {
            border-color: #4a90e2;
            box-shadow: 0 0 8px rgba(74, 144, 226, 0.2);
          }
        }
      }

      .check-all {
        color: #607d8b;
        font-weight: 500;
      }
    }

    .menu-tree {
      max-height: 400px;
      overflow-y: auto;
      background-color: #ffffff;
      border-radius: 8px;
      padding: 10px;
      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);

      .permission-tree {
        :deep(.el-tree-node) {
          &.is-current > .el-tree-node__content {
            background-color: #e6f2ff;
          }
        }

        .custom-tree-node {
          display: flex;
          align-items: center;
          width: 100%;

          .menu-icon {
            margin-right: 10px;
            color: #4a90e2;
          }

          .menu-title {
            color: #2c3e50;
            font-weight: 500;
          }
        }
      }
    }
  }
</style>
@/api/menu-api@/api/role-api@/utils/router-update-util